#include "Task.hpp"
#include "Channel.hpp"
#include "Common.hpp"
using work_t = std::function<void()>;




class Processpool
{

public:
    Processpool(int processnum,work_t work)
    :processnum(processnum),work(work)
    {

    }
    ~Processpool();

    // 1. 初始化进程池
    // channels 输出型参数
    // work 回调型参数
    int InitProcesspool()
    {
        // 2. 创建指定个数进程
        for (int i = 1; i <= processnum ; ++i)
        {
            // 1. 先有管道
            int pipefd[2] = {0};
            int rn = pipe(pipefd);
            if (rn < 0)
            {
                return PipeError;
            }

            // 2. 创建子进程
            pid_t id = fork();
            if (id < 0) // 创建子进程失败
            {
                return ForkError;
            }

            // 3. 建立信道
            if (id == 0) // 子进程
            {
                ::close(pipefd[1]); // 关掉写端
                // 关闭子进程中从父进程复制来的多余的打开的文件描述符
                std::cout<<"pid:"<<getpid()<<" 关闭文件描述符:";
                for(auto& c : channels)
                {
                    std::cout<<c.wFd()<<',';
                    c.Close();
                }std::cout<<"over"<<std::endl;


                // 从标准输入传入参数
                dup2(pipefd[0], 0);
                Worker();
                // 子进程运行完结束
                exit(0);
            }

            // 父进程
            ::close(pipefd[0]);
            channels.emplace_back(pipefd[1], id);
        }

        return OK;
    }
    // 2. 派发任务
    void DispatchTask()
    {
        int who = 0;
        int count = 20;
        // 2. 派发任务
        while (count--)
        {
            // a. 选择一个任务，整数
            int task_id = tm.SelectTask();
            // b. 选择一个子进程channel
            Channel &curr = channels[who++];
            who %= channels.size();

            std::cout << "######################" << std::endl;
            std::cout << "send " << task_id << " to " << curr.Name() 
            <<"，任务还剩： " << count << std::endl;
            std::cout << "######################" << std::endl;

            // c. 派发任务
            curr.Send(task_id);

            sleep(1);
        }
    }

    // 3. 退出进程池
    void CleanPprocesspool()
    {
        // 关闭写端文件描述符，读端会自动关闭
        for(auto& c :channels)
        {
            c.Close();
            pid_t rid = ::waitpid(c.Id(),nullptr,0);
            if(rid > 0)
            {
                std::cout<<"child "<<rid<< " wait ... success"<<std::endl;
            }
        }
        // // 父进程回收子进程
        // for(auto& c : channels)
        // {
        //     pid_t rid = ::waitpid(c.Id(),nullptr,0);
        //     if(rid > 0)
        //     {
        //         std::cout<<"child "<<rid<< " wait ... success"<<std::endl;
        //     }
        // }
    }

    void DebugPrint()
    {
        for (const auto &c : channels)
        {
            std::cout << c.Name() << std::endl;
        }
    }
private:
    std::vector<Channel> channels;
    int processnum;
    work_t work;
};








